<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>继承</title>
	</head>
	<body>
		<p>继承通过原型链实现</p>
	</body>
	<script>
	
	   //1普通原型链继承（无法传参，方法无法共享）
		function Box(){   //被继承的函数叫做超类型（父类，基类）
			this.name = 'lee';
		}
		function Desk(){   //继承的函数叫做子类型（子类，派生类）
			this.age =100;
			
		}
		function Table(){
			this.level = 'SSS';
		}
		
		//通过原型链继承，超类型实例化后的对象实例赋值给子类型的原型属性
		//new Box()会将Box构造里的信息和原型里的信息都交给Desk
		Desk.prototype = new Box();
		Table.prototype = new Desk();
		
		var desk = new Desk();
		alert(desk.age+','+desk.name);//100,lee
		
		var table = new Table();
		Table.prototype.age=200;
		alert(table.age);//200   就近原则，先从实例里查找，再到原型中
	
	//子类型从属于自己或者他的超类型
	 alert(desk instanceof Desk);//true
	 alert(desk instanceof Box);//true
	
	
	
	//未来解决引用共享和超类型无法传参问题，采用一种借用构造函数的技术
	//或者称为对象冒充（伪造对象、经典继承）的技术来解决这两种问题。
	
	
	//2使用对象冒充继承（方法无法共享问题）
	function FatherBox(name,age){
		this.name = name;
		this.age = age;
		this.family = ['哥哥','妹妹','姐姐'];//引用类型放在构造里不会被共享
	}
	Box.prototype.family ='奶奶';//原型（此处无法继承）
	function SunBox(name,age){
		FatherBox.call(this,name,age);//对象冒充
		//对象冒充只能继承构造函数里的信息
	}
	
	var boxOne = new SunBox('Tom',55);
	alert(boxOne.name+','+boxOne.age);//Tom 55
	alert(boxOne.family);//哥哥,妹妹,姐姐
	
	boxOne.family.push('爷爷');
	alert(boxOne.family);//哥哥,妹妹,姐姐,爷爷
	
	var boxTwo = new SunBox('Jck',55);
	alert(boxTwo.family);//哥哥,妹妹,姐姐
	
	
	
	//3组合继承方式，（构造函数+原型链）  常用
	//缺点是超类型CbIn 会被调用两次
	function CbIn(name,age){
		this.name = name;
		this.age = age;
		this.family = ['哥哥','妹妹','姐姐'];
		//方法
	}
	//构造函数里的方法，放在构造函数里导致每次实例化都会分配一个内存地址
	//所有最好放在原型里保证多次实例化只有一个地址
	
	CbIn.prototype.run = function (){//方法用原型实现
		return this.name+','+this.age+','+this.family;
	}
	
	function SunComBin (name,age){
		//第二次
		CbIn.call(this,name,age);//对象冒充无法继承原型
	}
	           // 第一次
	SunComBin.prototype = new CbIn();//原型链继承（继承原型）
	
	var someCb = new SunComBin('小红',19);
	alert(someCb.run());//小红,19,哥哥,妹妹,姐姐
	
	
	</script>
</html>
